Part 9 - এঙ্ক্রিপ্টেড প্রোগ্রামগুলির সাথে পরিচয় (Intro to Encrypted Programs)

বিশ্বাস করুন বা না করুন, এনক্রিপ্ট করা ডেটা দিয়ে গণনা করা সম্ভব। অন্য কথায়, একটি প্রোগ্রাম চালানো সম্ভব যেখানে প্রোগ্রামের সমস্ত ভেরিয়েবল এনক্রিপ্টেড

এই টিউটোরিয়ালে, আমরা এনক্রিপ্ট করা গণনার খুব প্রাথমিক সরঞ্জামগুলি দেখবো। বিশেষত, আমরা Secure Multi-Party Computation নামে পরিচিত একটি জনপ্রিয় পদ্ধতির উপর ফোকাস করতে যাচ্ছি। এই পাঠে, আমরা শিখব কীভাবে একটি এনক্রিপ্ট করা ক্যালকুলেটর তৈরি করতে হয়, যা এনক্রিপ্ট হওয়া সংখ্যায় গণনা সম্পাদন করতে পারে।

Authors:

References:

অনুবাদক:

Step 1: সুরক্ষিত মাল্টি-পার্টির গণনা ব্যবহার করে এনক্রিপশন (Encryption Using Secure Multi-Party Computation)

এসএমপিসি(SMPC) প্রথম নজরে "এনক্রিপশন" এর এক অদ্ভুত রূপ। কোনও ভেরিয়েবল এনক্রিপ্ট করার জন্য পাবলিক/প্রাইভেট চাবি(key) ব্যবহার করার পরিবর্তে প্রতিটি মান একাধিক shares-এ বিভক্ত হয়, যার প্রতিটি একটি ব্যক্তিগত চাবি(key) হিসাবে চালিত হয়। সাধারণত, এই shares ২ বা ততোধিক মালিকদের মাঝে বিতরণ করা হবে। সুতরাং, সমস্ত মালিকদের ডিক্রিপশন অনুমোদনের সম্মতির সাপেক্ষে ভেরিয়েবলটি ডিক্রিপ্ট(decrypt) করা হবে। সংক্ষেপে, প্রত্যেকের একটি ব্যক্তিগত চাবি আছে।

এনক্রিপ্ট Encrypt()

সুতরাং, ধরা যাক আমরা একটি ভেরিয়েবল x "এনক্রিপ্ট" করতে চেয়েছিলাম, আমরা নিম্নলিখিত পদ্ধতিতে এটি করতে পারি।

এনক্রিপশন ফ্লোটস বা বাস্তব সংখ্যা ব্যবহার করে না তবে এটি integer quotient ring নামক গাণিতিক স্পেসে ঘটে যা মূলত 0 এবং Q-1 এর মধ্যে বিদ্যমান পূর্ণসংখ্যা। যেখানে Q মৌলিক এবং "যথেষ্ট বড়" যেন স্পেসটি আমাদের পরীক্ষাগুলিতে আমরা যে সমস্ত সংখ্যা ব্যবহার করি তা ধারণ করতে পারে। বাস্তবে, একটি পূর্ণসংখ্যা মান x দেয়া হলে, আমরা x % Q করি যেন তা রিং এর মধ্যে ফিট করে। (এজন্যই আমরা x' > Q সংখ্যা ব্যবহার করা এড়িয়ে চলি ).


In [0]:
Q = 1234567891011

In [0]:
x = 25

In [0]:
import random

def encrypt(x):
    share_a = random.randint(-Q,Q)
    share_b = random.randint(-Q,Q)
    share_c = (x - share_a - share_b) % Q
    return (share_a, share_b,  share_c)

In [0]:
encrypt(x)


Out[0]:
(467284329259, -652559215416, 185274886182)

আপনি এখানে দেখতে পাচ্ছেন, আমরা আমাদের পরিবর্তনশীল x কে 3 টি আলাদা শেয়ারে বিভক্ত করেছি, যা 3 টি পৃথক মালিককে পাঠানো যেতে পারে।

ডিক্রিপ্ট Decrypt()

আমরা যদি এই 3 টি শেয়ার ডিক্রিপ্ট করতে চাইতাম, তবে আমরা কেবল তাদের একসাথে যোগ করতে পারি এবং ফলাফলের মডুলাস নিতে পারি (Mod Q)


In [0]:
def decrypt(*shares):
    return sum(shares) % Q

In [0]:
a,b,c = encrypt(25)

In [0]:
decrypt(a, b, c)


Out[0]:
25

গুরুত্বপূর্ণভাবে লক্ষ করুন যে আমরা যদি মাত্র দুটি শেয়ার দিয়ে ডিক্রিপ্ট করার চেষ্টা করি তবে ডিক্রিপশনটি কার্যকর হয় না!


In [0]:
decrypt(a, b)


Out[0]:
346980890071

সুতরাং, মানটি ডিক্রিপ্ট করার জন্য আমাদের সকল মালিকদের অংশ নেওয়া প্রয়োজন। এটি এইভাবে shares ব্যক্তিগত চাবির মতো কাজ করে, মানটি ডিক্রিপ্ট করার জন্য অবশ্যই এগুলির সবগুলোর উপস্থিতি থাকতে হবে।

Step 2: এসএমপিসি ব্যবহার করে বেসিক পাটিগণিত(Basic Arithmetic Using SMPC)

তবে সিকিউর মাল্টি পার্টি গণনার সত্যিকারের অসাধারণ একটি বৈশিষ্ট্য হলো যখন ভেরিয়েবলগুলি এনক্রিপ্ট করা থাকে সেখানেও গণনা সম্পাদন করতে পারা। নিম্নে সহজ সংযোজন প্রদর্শন করা হলো


In [0]:
x = encrypt(25)
y = encrypt(5)

In [0]:
def add(x, y):
    z = list()
    # the first worker adds their shares together
    z.append((x[0] + y[0]) % Q)
    
    # the second worker adds their shares together
    z.append((x[1] + y[1]) % Q)
    
    # the third worker adds their shares together
    z.append((x[2] + y[2]) % Q)
    
    return z

In [0]:
decrypt(*add(x,y))


Out[0]:
30

সফলতা (Success!!!)

এবং আপনি এটা পেয়ে গেলেন! যদি প্রতিটি কর্মী (পৃথকভাবে) তাদের শেয়ারগুলি একসাথে যোগ করে, তবে ফলস্বরূপ শেয়ারগুলি সঠিক মানটিতে ডিক্রিপ্ট হবে (25 + 5 == 30).

দেখা যাচ্ছে যে এসএমপিসি(SMPC) প্রোটোকল রয়েছে যা নিম্নলিখিত ক্রিয়াকলাপগুলির জন্য এই এনক্রিপ্ট করা গণনার অনুমতি দিতে পারে:

  • যোগ (যা আমরা সবেমাত্র দেখেছি)
  • গুণ
  • তুলনা

এবং এই প্রাথমিক অন্তর্নিহিত প্রিমিটিভস ব্যবহার করে, আমরা অবাধে গণনা সম্পাদন করতে পারি !!!

পরবর্তী বিভাগে, আমরা কীভাবে এই অপারেশনগুলি সম্পাদন করতে Pysyft লাইব্রেরি ব্যবহার করতে পারি তা শিখতে চলেছি!

Step 3: এসএমপিসি পাইসাইফ্ট ব্যবহার করে (SMPC Using PySyft)

পূর্ববর্তী বিভাগগুলিতে, আমরা এসএমপিসি কিভাবে কাজ করে সে নিয়ে কিছু বেসিক ধারণার রূপরেখা তৈরি করেছি । যাইহোক, বাস্তবে আমাদের এনক্রিপ্ট করা প্রোগ্রামগুলি লেখার সময় আমরা প্রিমিটিভ ক্রিয়াকলাপগুলির সমস্ত কিছু নিজের হাতে লিখতে চাই না। সুতরাং, এই বিভাগে আমরা পাইসাইফ্ট ব্যবহার করে এনক্রিপ্ট করা গণনা কীভাবে করতে হবে তার মূল বিষয়গুলি নিয়ে দেখবো। বিশেষত, আমরা পূর্বে উল্লিখিত ৩-টি প্রিমিটিভ কীভাবে করব তার উপর ফোকাস করতে যাচ্ছি: সংযোজন, গুণ এবং তুলনা।

প্রথমত, আমাদের কয়েকটি ভার্চুয়াল ওয়ার্কার তৈরি করতে হবে (যা আশা করি আপনি এখন আমাদের আগের টিউটোরিয়ালগুলির সাথে পরিচিত আছেন)।


In [0]:
import torch
import syft as sy
hook = sy.TorchHook(torch)

bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
bill = sy.VirtualWorker(hook, id="bill")

সাধারণ এনক্রিপশন / ডিক্রিপশন (Basic Encryption/Decryption)

এনক্রিপশন(Encryption) কোনও পাইসাইফ্ট টেনসর নেওয়া এবং .share() কল করার মতোই সহজ। ডিক্রিপশন শেয়ারড ভেরিয়েবলে .get() কল করার মতোই সহজ।


In [0]:
x = torch.tensor([25])

In [0]:
x


Out[0]:
tensor([25])

In [0]:
encrypted_x = x.share(bob, alice, bill)

In [0]:
encrypted_x.get()


Out[0]:
tensor([25])

এনক্রিপ্ট করা মানগুলিকে আত্মপ্রকাশ করে (Introspecting the Encrypted Values)

আমরা যদি Bob, Alice এবং Bill এর কর্মীদের কাছ থেকে দেখি, আমরা যে শেয়ারগুলি তৈরি হবে তা দেখতে পাব!


In [0]:
list(bob._tensors.values())


Out[0]:
[]

In [0]:
x = torch.tensor([25]).share(bob, alice, bill)

In [0]:
# Bob's share
bobs_share = list(bob._tensors.values())[0]
bobs_share


Out[0]:
tensor([1061525539398735196])

In [0]:
# Alice's share
alices_share = list(alice._tensors.values())[0]
alices_share


Out[0]:
tensor([424539979954823758])

In [0]:
# Bill's share
bills_share = list(bill._tensors.values())[0]
bills_share


Out[0]:
tensor([3125620499073828975])

এবং যদি আমরা চাইতাম, আমরা আগে যে বিষয়গুলি নিয়ে আলোচনা করেছি সেগুলি ব্যবহার করে আমরা এই মানগুলি ডিক্রিপ্ট করতে পারি !!!


In [0]:
(bobs_share + alices_share + bills_share)


Out[0]:
tensor([25])

যেমন আপনি দেখতে পাচ্ছেন, আমরা যখন ফোন করেছি.share() এটি কেবলমাত্র 3 টি শেয়ারে মূল্য বিভক্ত করে এবং প্রতিটি দলের কাছে একটি ভাগ প্রেরণ করে!

এনক্রিপ্ট করা পাটীগণিত (Encrypted Arithmetic)

এবং এখন আপনি দেখতে পাচ্ছেন যে আমরা অন্তর্নিহিত মানগুলিতে গাণিতিক সম্পাদন করতে পারি! এপিআইটি(API) এমনভাবে তৈরি করা হয়েছে যাতে আমরা পাইটর্চ টেনসোর(PyTorch tensors) মতো সাধারণভাবে পাটিগণিত সম্পাদন করতে পারি।


In [0]:
x = torch.tensor([25]).share(bob,alice)
y = torch.tensor([5]).share(bob,alice)

In [0]:
z = x + y
z.get()


Out[0]:
tensor([30])

In [0]:
z = x - y
z.get()


Out[0]:
tensor([20])

এনক্রিপ্ট করা গুণ (Encrypted Multiplication)

গুণনের জন্য আমাদের একটি অতিরিক্ত দল দরকার যারা ধারাবাহিকভাবে র‍্যান্ডম সংখ্যা তৈরি করার জন্য দায়ী (এবং অন্য দলের কোনটির সাথে মিলিত না হয়ে)। আমরা এই ব্যক্তিকে "ক্রিপ্টো সরবরাহকারী/crypto provider" বলি। সকল নিবিড় উদ্দেশ্যে, ক্রিপ্টো সরবরাহকারী কেবল একটি অতিরিক্ত ভার্চুয়াল ওয়ার্কার, তবে এটি স্বীকার করা জরুরী যে ক্রিপ্টো সরবরাহকারী কোনও "মালিক" নয় যার জন্য তার নিজের অংশীদারি নেই। তবে সে এমন কেউ যাকে বিশ্বাস করতে হবে যেন সে অন্য কোন শেয়ারহোল্ডারের সাথে মিশে না যায়।


In [0]:
crypto_provider = sy.VirtualWorker(hook, id="crypto_provider")

In [0]:
x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)

In [0]:
# multiplication

z = x * y
z.get()


Out[0]:
tensor([125])

আপনি ম্যাট্রিক্স গুণও করতে পারেন


In [0]:
x = torch.tensor([[1, 2],[3,4]]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([[2, 0],[0,2]]).share(bob,alice, crypto_provider=crypto_provider)

In [0]:
# matrix multiplication

z = x.mm(y)
z.get()


Out[0]:
tensor([[2, 4],
        [6, 8]])

এনক্রিপ্টেড তুলনা (Encrypted comparison)

প্রাইভেট ভ্যালুগুলোর মধ্যে প্রাইভেট তুলনা করাও সম্ভব। আমরা এখানে SecureNN প্রোটোকলে নির্ভর করি, যার বিবরণ পাওয়া যাবে এখানে। তুলনার ফলাফলটি একটি ব্যক্তিগত শেয়ারড টেনসরও।


In [0]:
x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)

In [0]:
z = x > y
z.get()


Out[0]:
tensor([1])

In [0]:
z = x <= y
z.get()


Out[0]:
tensor([0])

In [0]:
z = x == y
z.get()


Out[0]:
tensor([0])

In [0]:
z = x == y + 20
z.get()


Out[0]:
tensor([1])

আপনি max অপারেশনও করতে পারেন


In [0]:
x = torch.tensor([2, 3, 4, 1]).share(bob,alice, crypto_provider=crypto_provider)
x.max().get()


Out[0]:
tensor([4])

In [0]:
x = torch.tensor([[2, 3], [4, 1]]).share(bob,alice, crypto_provider=crypto_provider)
max_values, max_ids = x.max(dim=0)
max_values.get()


Out[0]:
tensor([4, 3])

অভিনন্দন সম্প্রদায় যোগদানের সময়! (Congratulations!!! - Time to Join the Community!)

এই নোটবুক টিউটোরিয়ালটি সম্পন্ন করার জন্য অভিনন্দন। আপনি যদি এটি উপভোগ করেন এবং গোপনীয়তা সংরক্ষণ, AI এবং AI সরবরাহ চেইনের (ডেটা) বিকেন্দ্রীভূত মালিকানার দিকে আন্দোলনে যোগ দিতে চান, আপনি নিম্নলিখিত উপায়ে এটি করতে পারেন।

গিটহাবে পাইসিফ্ট কে স্টার দিন (Star PySyft on GitHub)

আমাদের সম্প্রদায়কে সাহায্য করার সবচেয়ে সহজ উপায় হল রিপোসিটোরি গুলোতে ষ্টার করা এটি আমরা যে অসাধারণ সরঞ্জামগুলি তৈরি করছি তার সচেতনতা বাড়াতে সহায়তা করে।

আমাদের স্ল্যাকে যোগ দিন (Join our Slack!)

সর্বশেষতম অগ্রগতিতে আপ টু ডেট রাখার সর্বোত্তম উপায় হ'ল আমাদের সম্প্রদায়ে যোগদান করা। আপনি ফর্মটি পূরণ করে এটি করতে পারেন http://slack.openmined.org

একটি কোড প্রকল্পে যোগদান করুন! (Join a Code Project!)

আমাদের সম্প্রদায়ে অবদান রাখার সর্বোত্তম উপায় হল কোড অবদানকারী হয়ে উঠুন! যে কোনও সময় আপনি পাইসাইফ্ট গিটহাবে ইস্যু পৃষ্ঠাতে যেতে পারেন এবং "প্রকল্পগুলি" এর জন্য ফিল্টার করতে পারেন। এটি আপনাকে শীর্ষ স্তরের সমস্ত টিকিট দেখিয়ে দেবে যে আপনি কোন প্রকল্পগুলিতে যোগদান করতে পারেন তার একটি ওভারভিউ দেয়! আপনি যদি কোনও প্রকল্পে যোগ দিতে না চান তবে আপনি কিছুটা কোডিং করতে চান তবে আপনি "ভাল প্রথম ইস্যু" চিহ্নিত গিথুব ইস্যুগুলি অনুসন্ধান করে আরও "ওয়ান অফ" মিনি-প্রকল্পগুলির সন্ধান করতে পারেন।

দান করুন (Donate)

আপনার যদি আমাদের কোডবেসে অবদান রাখার সময় না থাকে তবে তবুও সমর্থন দিতে চান, আপনি আমাদের ওপেন কালেক্টিভেরও Backer হয়ে উঠতে পারেন। সমস্ত অনুদান আমাদের ওয়েব হোস্টিং এবং অন্যান্য সম্প্রদায় ব্যয় যেমন হ্যাকাথন এবং মিটাপগুলির (hackathons and meetups!) দিকে যায়।


In [0]: